using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommerceOne.Domains.Commons;
using CommerceOne.Domains.IRepositories;
using CommerceOne.Models.Entities;
namespace CommerceOne.Domains.SqlRepositories
{
    public class SqlProductRepository :SqlRepositoryBase, IProductRepository
    {
        /// <summary>
        /// Gets the top newest product.
        /// </summary>
        /// <param name="top">The top.</param>
        /// <returns></returns>
        public List<Product> GetTopNewestProduct(int top)
        {
            return this.SqlContext.Products.Take(top).OrderByDescending(p=>p.StartSellingDate).ToList();
        }

        /// <summary>
        /// Gets the products.
        /// </summary>
        /// <param name="categoryId">The category id.</param>
        /// <param name="sortingType">Type of the sorting.</param>
        /// <param name="page">The page.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="totalRecords">The total records.</param>
        /// <returns></returns>
        public List<Product> GetProducts(int categoryId, ProductSortType sortingType, int page, int pageSize, out int totalRecords )
        {
            if (pageSize <= 0) throw new Exception("PageSize must be greater than 0.");
            if (page <= 0) page = 1;
            totalRecords = 0;
            IQueryable<Product> queryable = this.SqlContext.Products.Where(p => p.SubCategoryID == categoryId);
            totalRecords = queryable.Count();
            int skip = pageSize*(page - 1);

            switch (sortingType)
            {
                case ProductSortType.PriceDesc:
                    return queryable.OrderByDescending(p => p.ListPrice).Skip(skip).Take(pageSize).ToList();
                case ProductSortType.PriceAsc:
                    return queryable.OrderBy(p => p.ListPrice).Skip(skip).Take(pageSize).ToList();
                case ProductSortType.NameDesc:
                    return queryable.OrderByDescending(p => p.Name).Skip(skip).Take(pageSize).ToList();
                case ProductSortType.NameAsc:
                    return queryable.OrderBy(p => p.Name).Skip(skip).Take(pageSize).ToList();
                case ProductSortType.InStockFirst:
                    return queryable.OrderByDescending(p => p.InStockQuantity).Skip(skip).Take(pageSize).ToList();
                default:
                    return queryable.OrderByDescending(p => p.ID).Skip(skip).Take(pageSize).ToList();
            }
        }

        /// <summary>
        /// Gets the product by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public Product GetProductById(int id)
        {
            return this.SqlContext.Products.FirstOrDefault(p => p.ID == id);
        }

        #region Singleton Instance
        private static SqlProductRepository _instance;
        public static SqlProductRepository Instance
        {
            get { return _instance ?? (_instance = new SqlProductRepository()); }
        }
        #endregion
    }
} 
